/*=============================================================
* 	Copyright (C) 2024 USTC All rights reserved.
* 	
* 	filename : synapse.hh
* 	Author: Wei Jinsong
* 	Mail: vitus@mainl.ustc.edu.cn
* 	Date 2024-05-25
* 	Abstract 
*       
*
=============================================================*/
#ifndef __SYNAPSE_H__
#define __SYNAPSE_H__

#include <vector>
#include "common.h"
#include "systemc.h"
#include "tlm.h"

class NeuronSynapse
    : public sc_core::sc_module
    , public SynapseInterface<SpikePayload>
{
public:
    NeuronSynapse(sc_module_name name):sc_module(name)
    {}
};

class SpikeNeuronSynapse 
    : public NeuronSynapse
{
private:
    SpikePayload* _dendrites;
    SpikePayload* _axons;
    vector<vector<int>> _int_axons;
    vector<vector<double>> _double_denrites; 
public :
    SC_HAS_PROCESS(SpikeNeuronSynapse);
    SpikeNeuronSynapse(string name, sc_clock& clock, string file);
    ~SpikeNeuronSynapse();
    
    void set_params(string file);
    vector<SpikePayload*> get_axon(SpikePayload* );
    vector<SpikePayload*> get_dendrite(SpikePayload* );
};

class FSNeuronSynapse
    : public NeuronSynapse
{
private:
    SpikePayload* _dendrites;
    SpikePayload* _axons;
    struct ConvPoolParam{
        int ic=0;
        int oc=0;
        int kh=0;
        int kw=0;
        int sh=0;
        int sw=0;
        int ph=0;
        int pw=0;
    };

    string type;
    ConvPoolParam _convParam;
    ConvPoolParam _poolParam;
    
    vector<vector<int>> _int_axons;
    vector<vector<vector<vector<double>>>> _conv_weights;
    vector<vector<double>> _linear_weights;
public:
    SC_HAS_PROCESS(FSNeuronSynapse);
    FSNeuronSynapse(string name, sc_clock& clock, string file);
    ~FSNeuronSynapse();
    
    void set_params(string file);
    vector<SpikePayload*> get_axon(SpikePayload*);
    vector<SpikePayload*> get_dendrite(SpikePayload*);
};

class FSNeuronTimer
    :public sc_core::sc_module 
    ,public TimerInterface
{
private:
    int32_t _Step;
    int32_t _Phase;
    int32_t _Tick;

    int32_t StepNum;
    int32_t PhaseNum;
    int32_t TickNum;

public:
    SC_HAS_PROCESS(FSNeuronTimer);
    FSNeuronTimer(sc_module_name, uint32_t step_num, uint32_t tick_num);

    int get_step() override;
    int get_phase() override;
    bool set_tick() override;
};

#endif
